package com.stars.easyms.monitor.shiro;

import com.stars.easyms.base.util.ApplicationContextHolder;
import com.stars.easyms.base.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>className: EasyMsShiroAuthorityHandler</p>
 * <p>description: EasyMs的shiro权限管理处理者</p>
 *
 * @author guoguifang
 * @date 2019-11-22 16:25
 * @since 1.4.1
 */
@Slf4j
final class EasyMsShiroAuthorityHandler {

    void handle(List<ShiroAuthorityFunc> shiroAuthorityFuncList) {
        // 获取ShiroFilterFactoryBean类
        ShiroFilterFactoryBean shiroFilterFactoryBean = ApplicationContextHolder.getBean(ShiroFilterFactoryBean.class);
        if (shiroFilterFactoryBean == null) {
            return;
        }

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(256);
        // 按照顺序打印扫描到的接口信息
        for (ShiroAuthorityFunc shiroAuthorityFunc : shiroAuthorityFuncList) {
            log.info("Found {} shiro authority func: {}!", shiroAuthorityFunc.getShiroAuthorityModuleName(),
                    shiroAuthorityFunc.getClass().getCanonicalName());
            filterChainDefinitionMap.putAll(shiroAuthorityFunc.getFilterChainDefinitionMap());
        }
        filterChainDefinitionMap.putAll(shiroFilterFactoryBean.getFilterChainDefinitionMap());
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        try {
            AbstractShiroFilter shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
            if (shiroFilter != null) {
                FilterChainResolver filterChainResolver = shiroFilter.getFilterChainResolver();
                if (filterChainResolver instanceof PathMatchingFilterChainResolver) {
                    PathMatchingFilterChainResolver pathMatchingFilterChainResolver = (PathMatchingFilterChainResolver) filterChainResolver;
                    Method createFilterChainManagerMethod = ReflectUtil.getMatchingMethod(ShiroFilterFactoryBean.class, "createFilterChainManager");
                    createFilterChainManagerMethod.setAccessible(true);
                    FilterChainManager filterChainManager = (FilterChainManager) ReflectionUtils.invokeMethod(createFilterChainManagerMethod, shiroFilterFactoryBean);
                    pathMatchingFilterChainResolver.setFilterChainManager(filterChainManager);
                }
            }
        } catch (Exception e) {
            log.error("Initialization shiroFilter failed!", e);
        }
    }

}